Funciones en Kotlin

En este artículo veremos cómo definir e invocar funciones en Kotlin usando la palabra reservada fun.

Daremos un repaso para ver recursividad, funciones variádicas, vacías, de una sola línea, sobrecarga de métodos, funciones con nombres de parámetros, funciones como variables y mucho más.

Factorial en Kotlin – Ejemplo de función con recursividad

Una función es una forma de separar y dividir la lógica de nuestros programas. La mayoría de veces, las funciones en Kotlin reciben argumentos, los procesan y devuelven un resultado.

A veces hay funciones que no regresan nada, o que no reciben nada; pero que igualmente sirven para algo.

Sintaxis de una función en Kotlin

La sintaxis o anatomía de una función en Kotlin es la siguiente:

fun nombre_de_la_función(argumento: Tipo, otroArgumento: OtroTipo, ...): TipoDeValorQueDevuelve{
  // Cuerpo de la función
  return UnValor
}

Como puedes ver, la función se define usando fun seguida de su nombre.

Entre los paréntesis van los argumentos que la función recibe. Si la función no recibe argumentos, entonces deja los paréntesis vacíos.

Después de los paréntesis, se indica el tipo de valor que la función regresa, separado por :. Si la función no regresa nada, no es necesario indicar el tipo de retorno, o puede ser especificado por Unit.

Dentro de las llaves se procesan los argumentos; o se hace lo que se tenga que hacer, y se devuelve un resultado cuando es requerido así.

Ejemplos de funciones en Kotlin

Para dejar más clara la declaración de funciones en Kotlin, veamos varios ejemplos.

Suma de números

La siguiente función de Kotlin suma dos números:

// Definir la función
fun sumar(numero1: Int, numero2: Int): Int {
    return numero1 + numero2
}
// Invocarla
val resultado = sumar(20, 1)
println("La suma es: $resultado")

Es muy simple, recibimos dos números de tipo Int y regresamos un Int.

Funciones de una sola línea

Si nuestras funciones no tienen un cuerpo muy grande, o de hecho no lo tienen (como el ejemplo de arriba) podemos convertirlas en funciones de Kotlin más cortas:

// Definir la función
fun sumar(numero1: Int, numero2: Int) = numero1 + numero2
// Invocarla
val resultado = sumar(20, 1)

En este caso no se indica el valor de retorno, ni se usan llaves. Solo se regresa el resultado, y el compilador infiere el tipo por nosotros.

Sobrecarga de funciones y argumentos opcionales

La sobrecarga de métodos o funciones es definir funciones con el mismo nombre pero distinto tipo de argumentos; de esta manera podemos hacer que tengan parámetros opcionales.

Veamos un ejemplo de una función en Kotlin en donde definimos la función que suma 2 o 3 números:

// Definir funciones sobrecargadas
fun sumar(numero1: Int, numero2: Int) = numero1 + numero2
fun sumar(numero1: Int, numero2: Int, numero3: Int) = numero1 + numero2 + numero3
// Invocarlas
val resultado = sumar(20, 1)
println("La suma es: $resultado")
val otroResultado = sumar(28, 11, 96)
println("La suma es: $otroResultado")

Así podrías hacer con varios argumentos de las funciones. No siempre vas a sumar, a veces serán funciones más complejas.

Podrías crear una función que reciba argumentos opcionales, es decir, que reciba un menor número de argumentos y asigne valores por defecto a los otros.

Nota: más abajo veremos las funciones variádicas.

Funciones que no devuelven nada

Como lo dije, hay funciones que no devuelven nada y que sí reciben algo. Veamos un ejemplo de una función en Kotlin que saluda:

fun saludar(nombre: String): Unit{
    println("Hola $nombre")
}
saludar("Parzibyte")

En este caso indicamos que devolverá Unit, el equivalente a void en C.

La función recibe el nombre del usuario, pero no devuelve nada, simplemente imprime un mensaje.

Si la función devuelve Unit, entonces podemos omitir el tipo de valor que regresa. La misma función de arriba puede escribirse así:

fun saludar(nombre: String){
    println("Hola $nombre")
}
saludar("Parzibyte")

Funciones en Kotlin que no reciben nada

También existen funciones que no reciben nada pero que pueden devolver algo. Por ejemplo, la siguiente función devuelve el nombre de un usuario:

fun obtenerNombre(): String{
    return "Luis Cabrera Benito"
}

val nombre = obtenerNombre()
println("El nombre es: $nombre")

Recuerda que como estamos devolviendo un valor, podríamos hacerla en una línea:

fun obtenerNombre() = "Luis Cabrera Benito"

val nombre = obtenerNombre()
println("El nombre es: $nombre")

Nota: obviamente, en aplicaciones de la vida real, esta función podría ser más compleja; leería de una sesión, de una base de datos, etcétera.

Funciones vacías

Igualmente hay funciones que no reciben ni devuelven nada, pero que hacen algo. Un ejemplo podría ser el siguiente:

fun registrarUsoDeApp(){
    enviarAlServidor(fechaActual())
}

Funciones variádicas o con argumentos “infinitos”

En el ejemplo de arriba, si quisieras sumar 4 números definirías otra función; si quisieras sumar 5, otra más. Y así sucesivamente.

En Kotlin existen las funciones con argumentos variados que pueden ser 0 o infinitos. Veamos la función que suma números:

// Definir función con varios argumentos
fun sumar(vararg numeros: Int): Int {
    var suma = 0
    for (numero in numeros){
        suma += numero
    }
    return suma
}
// Invocar función variádica
val resultado = sumar(20, 1)
println("La suma es: $resultado")
val otroResultado = sumar(28, 11, 96)
println("La suma es: $otroResultado")
val unResultadoMas = sumar(1, 2, 3, 4, 5, 6, 7, 8, 9)
println("La suma es: $unResultadoMas")

Para indicar que son argumentos sin un número definido se usa la palabra reservada vararg. Si no hay argumentos, entonces se devolvería 0.

Varargs y argumentos

Hay funciones que requieren argumentos definidos, y argumentos variados.

Para lograr esto podemos definir los argumentos requeridos al inicio, y dejar los variados al final:

fun saludarAmigos(nombre: String, vararg nombreAmigos: String){
    for (nombreDeAmigo in nombreAmigos){
        println("$nombre saluda a $nombreDeAmigo")
    }
}

saludarAmigos("Luis", "Pedro", "José", "Raúl", "Ignacio")
/*
Salida:

Luis saluda a Pedro
Luis saluda a José
Luis saluda a Raúl
Luis saluda a Ignacio
*/

Como ves, los argumentos que no son variadic, se definen como cualquier otro argumento.

Recuerda que los argumentos podrían ser de cualquier tipo, y puedes poner más de uno requerido, solo no olvides poner los variádicos al final.

Nombres en los argumentos de las funciones en Kotlin

Hay algunas funciones que tienen muchos argumentos, de distintos tipos y sabores.

Si no tenemos un buen IDE que nos diga el nombre de los mismos o no tenemos memoria fotográfica, tendremos problemas recordando el nombre. Por ejemplo:

fun agregarPostAlBlog(id: Int, autor: String, titulo: String, contenido: String, fechaCreacion: String, permiteComentarios: Boolean, conteoComentarios: Int){
    // Aquí crear el post ;)
}

agregarPostAlBlog(1, "parzibyte", "Funciones en Kotlin", "Bla bla", "2019-07-18", false, 0)

Ahora imagina que lees la invocación a la función (la de la línea 5) y la definición de la función está en otro lugar. ¿Cómo sabes qué cosa indica cada uno?

A nuestro rescate vienen los nombres de los argumentos. El programador que escribió lo de la línea 5 pudo mejor hacerlo así:

fun agregarPostAlBlog(id: Int, autor: String, titulo: String, contenido: String, fechaCreacion: String, permiteComentarios: Boolean, conteoComentarios: Int){
    // Aquí crear el post ;)
}

agregarPostAlBlog(
    id = 1, 
    autor = "parzibyte", 
    titulo = "Funciones en Kotlin",
    contenido = "Bla bla",
    fechaCreacion = "2019-07-18",
    permiteComentarios = false,
    conteoComentarios = 0
)

De esta manera, cuando se lee la llamada a la función, se sabe a qué pertenece cada argumento.

Ah, y otra cosa buena de esto es que cuando usamos esta forma, el orden no importa, mientras mandemos todos.

La misma llamada podría ser así:

fun agregarPostAlBlog(id: Int, autor: String, titulo: String, contenido: String, fechaCreacion: String, permiteComentarios: Boolean, conteoComentarios: Int){
    // Aquí crear el post ;)
}

agregarPostAlBlog(
    autor = "parzibyte", 
    titulo = "Funciones en Kotlin",
    conteoComentarios = 0,
    contenido = "Bla bla",
    fechaCreacion = "2019-07-18",
    id = 1, 
    permiteComentarios = false
)

Recursión o recursividad en Kotlin

Una función sí puede ser llamada dentro de sí misma, y a eso se le llama recursión o recursividad.

No solo Kotlin lo permite; lo permiten varios lenguajes. Recuerda que estas funciones deben tener una salida.

Veamos un ejemplo que obtiene el factorial de un número usando recursividad.

fun factorial(numero: Float): Float {
    if (numero > 1){
        return numero * factorial(numero - 1)
    } else {
        return numero
    }
}

println(factorial(5f))

Nota: con Kotlin podríamos simplificar la función usando un return if, pero eso es cosa de otro post.

Como puedes ver, la condición de salida es que el número sea menor que 1. Si es mayor que 1 entonces se devuelve el número, multiplicado por el factorial de ese número – 1.

En la vida real la recursividad se usa para múltiples cosas; yo la he usado para reintentar la comunicación con un servidor (mientras haya errores, la función se vuelve a llamar)

Literales en funciones (function literal)

Se pueden definir funciones literales en Kotlin, que son como funciones de una línea. Por ejemplo:

val saludarDeNuevo = { nombre: String -> println("Hola $nombre") }

saludarDeNuevo("Luis")

Este tipo de funciones se usa más como anónimas y de un solo uso.

Funciones como variables

Las funciones se pueden almacenar en variables:

val restar = fun(n1: Int, n2: Int): Int{
    return n1 - n2
}

restar(12, 2)

Es casi lo mismo que definir una función normal, pero en este caso podríamos pasar esta función como argumento a otra función. Sí, así de complicado suena, pero es muy útil.

Funciones como argumentos

Se pueden pasar funciones como argumentos, a otras funciones. La función puede ser almacenada en una función o definirse en la llamada.

Veamos el siguiente ejemplo que multiplica dos números pero no regresa el resultado, sino que llama a la función que le indiquemos con el mismo:

fun multiplicarYLlamar(n1: Float, n2: Float, callback: (Float) -> Unit ){
    val resultado = n1 * n2
    callback(resultado)
}

multiplicarYLlamar(10f, 4f, fun (resultado: Float){
    println("El resultado es: $resultado")
})

Aunque se vea complicado, esto es útil cuando usamos callbacks en Kotlin.

Fijate en la sintaxis tanto de la definición, como de la llamada.

Al invocar a la función definimos la función de callback, pero podríamos haberla guardado en una variable y pasarla como argumento.

Se pueden pasar todo tipo de funciones como argumentos, con variables argumentos dentro de ellas, y así sucesivamente.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *